local INT = CurseProfiler.INT;
local TUPLE = CurseProfiler.TUPLE;
local STRING = CurseProfiler.STRING;

function CurseProfiler.makeSerializedPosition(pos)
	if pos == nil or pos.x == nil then
		pos = {x = 0, y = 0, zone = 0, area = 0};
	end
	local position = {};
	position[TUPLE {
		INT("Int32", math.floor(pos.x+.5)),
		INT("Int32", math.floor(pos.y+.5)),
		INT("UInt16", pos.zone),
	}] = true;
	return position;
end
local POSITION = CurseProfiler.makeSerializedPosition;


function CurseProfiler.SerializeRest()

    
	-- Creatures
	local creatures = {};
	for k,v in pairs(CurseProfiler.Data.NPCS) do
		local positions = {};
		for kk,vv in pairs(v.pos) do
			positions[TUPLE {
				INT("Int32", math.floor(vv.x)),
				INT("Int32", math.floor(vv.y)),
				INT("UInt16", vv.zone)
			}] = true;
		end
		local store = {};
		for kk,vv in pairs(v.store) do
			store[TUPLE {
				INT("Int32",vv.id),
				INT("Int32", vv.price),
				INT("Int16", vv.type)
			}] = true;
		end
		creatures[TUPLE {
			STRING(v.name),        
			INT("Byte", v.minlevel),
			INT("Byte", v.maxlevel),
			positions,
			store
		}] = true;
    	end

	-- objects
	local objects = {};
	for k,v in pairs(CurseProfiler.Data.Objects) do
		local positions = {};
		for kk,vv in pairs(v.pos) do
			positions[TUPLE {
				INT("Int32", math.floor(vv.x)),
				INT("Int32", math.floor(vv.y)),
				INT("UInt16", vv.zone)
			}] = true;
		end

		objects[TUPLE {
			STRING(v.name),        
			positions,
		}] = true;
    	end

	--Quests
	local quests = {};
	for k,v in pairs(CurseProfiler.Data.Quests) do
		quests[TUPLE {
			STRING(v.name),     
			INT("Int16", v.catalog),
			INT("Byte", v.daily),
			INT("Int32", v.money),
			INT("Int32", v.tp),
			INT("Int32", v.xp),
			INT("Int32", v.startnpc),
			INT("Int32", v.endnpc)
		}] = true;
    	end	

	--locations
	local locations = {};
		for kk,vv in pairs(CurseProfiler.Data.StaticLocations) do
			locations[TUPLE {
				INT("Int32", kk),
				INT("Int32", math.floor(vv.x)),
				INT("Int32", math.floor(vv.y)),
				INT("UInt16", vv.zone)
			}] = true;
		end

	--player
	local player = {};
	local equip = {};
	local stats = {};
	local skills = {};
	local tradeskills = {};
	local recipes = {};
	for kk,vv in pairs(CurseProfiler.Data.Player.Equipment) do
			equip[TUPLE {
				INT("Int32", kk),
				INT("Int32", tonumber(vv.level)),
				STRING(vv.name),
				STRING(vv.text)
			}] = true;
	end

	for kk,vv in pairs(CurseProfiler.Data.Player.Stats) do
			stats[TUPLE {
				INT("Int32", kk),
				INT("Int32", math.floor(vv))
			}] = true;
	end
	for kk,vv in pairs(CurseProfiler.Data.Player.Skills) do
			skills[TUPLE {
				INT("Int32", kk),
				INT("Int32", math.floor(vv.level)),
				INT("Int32", vv.max)
			}] = true;
	end
	for kk,vv in pairs(CurseProfiler.Data.Player.Professions) do
			tradeskills[TUPLE {
				INT("Int32", kk),
				INT("Int32", math.floor(vv.level)),
				INT("Int32", vv.max)
			}] = true;
	end
	for kk,vv in pairs(CurseProfiler.Data.Player.Recipes) do
			recipes[TUPLE {
				INT("Int32", vv)
			}] = true;
	end
			player[TUPLE {
				STRING(CurseProfiler.Data.Player.name), 
				STRING(CurseProfiler.Data.Player.server), 
				INT("Byte", CurseProfiler.Data.Player.sex),
				STRING(CurseProfiler.Data.Player.mainClass), 
				STRING(CurseProfiler.Data.Player.subClass), 
				INT("Int32", CurseProfiler.Data.Player.mainLevel),
				INT("Int32", CurseProfiler.Data.Player.subLevel),
				INT("Int32", CurseProfiler.Data.Player.mainXP),
				INT("Int32", CurseProfiler.Data.Player.mainMaxXP),
				INT("Int32", CurseProfiler.Data.Player.subXP),
				INT("Int32", CurseProfiler.Data.Player.subMaxXP),
				STRING(CurseProfiler.Data.Player.guild),
				equip,
				stats,
				skills,
				tradeskills,
				recipes
			}] = true;	
	local servers = {};	
			servers[TUPLE {
				STRING(CurseProfiler.Data.Server.name)
			}] = true;	

	--guilds
	local guilds = {};
	if(CurseProfiler.Data.Player.Guild.level ~= nil) then
			local members = {};
			for k,v in pairs(CurseProfiler.Data.Player.Guild.members) do
				members[TUPLE {
					STRING(v.name),
					INT("Int32", v.rank),
					INT("Int32", v.level),
					INT("Int32", v.sublevel),
					STRING(v.class),
					STRING(v.subclass),
					STRING(v.title)
				}] = true;
			end
			guilds[TUPLE {
				STRING(CurseProfiler.Data.Player.Guild.name),
				STRING(CurseProfiler.Data.Player.Guild.leader),
				INT("Int32", CurseProfiler.Data.Player.Guild.level),
				members
			}] = true;
	end

	--mall
	local mall = {};
	for k,v in pairs(CurseProfiler.Data.Mall) do
				mall[TUPLE {
					STRING(k),
					INT("Int32", v.diamonds),
					INT("Int32", v.count)
				}] = true;
	end
    
	return {
		creatures,
		quests,
		locations,
		player,
		servers,
		guilds,
		mall,
		objects

	};
end


function CurseProfiler.SerializeData()
	if(CurseProfiler.Data.Server == nil) then
		return;
	end
	-- Global Settings
	local global_settings = {}
	
	global_settings[TUPLE {
			INT("Int32",CurseProfiler.Version),
			STRING(GetVersion()),
			STRING(CurseProfiler.Data.Server.name)
			
		}] = true;
	
	local data;
	data = CurseProfiler.SerializeRest();     
	table.insert(data, 1, global_settings)
	
	local x = CurseProfiler.base64encode(CurseProfiler.serialize(CurseProfiler.TUPLE(data)));
	return x;
end

